package so.sao.code.service.web.portal;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import so.sao.accessories.dto.request.PackDataInfoRequest;
import so.sao.accessories.dto.response.PackDataInfoResponse;
import so.sao.accessories.feign.client.PackDataInfoClient;
import so.sao.auth.autoreg.annotation.ButtonResource;
import so.sao.auth.autoreg.annotation.MenuResource;
import so.sao.code.dto.request.TagScrapRequest;
import so.sao.code.service.domain.entity.TagBatch;
import so.sao.code.service.domain.entity.TagScrap;
import so.sao.code.service.infrastructure.SessionContext;
import so.sao.code.service.infrastructure.enums.TAG_BATCH_TYPE;
import so.sao.code.service.infrastructure.model.vo.PackageCodeInfoVO;
import so.sao.code.service.infrastructure.model.vo.SingleCodeInfoVO;
import so.sao.code.service.infrastructure.model.vo.TagBatchVO;
import so.sao.code.service.service.TagBatchService;
import so.sao.code.service.service.TagScrapService;
import so.sao.sso.common.CommonConstants;
import so.sao.top.core.util.PageUtil;

@Api(tags = "tagscrap", description = "Portal标签报废")
@RestController
@MenuResource(perm = "*", cls = "codeMgmt", order = 60)
@MenuResource(perm = "scrap.*", url = "scrap")
@RequestMapping("portal/tagscrap")
public class TagScrapController {
	@Autowired
	TagScrapService tagScrapService;

	@Autowired
	private TagBatchService tagBatchService;
	@Autowired
	PackDataInfoClient packDataInfoClient;
	@Autowired
	SessionContext context;

	/**
	 * 标签报废操作
	 * 
	 * @param tagScrapRequest
	 * @return
	 * @throws Exception 
	 */
	@ApiOperation(value = "标签报废", notes = "同时支持按批次、码段、单码、箱码报废")
	@ApiImplicitParam(name = "tagScrapRequest", value = "码报废请求", required = true, dataType = "TagScrapRequest", paramType = "body")
	@PostMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@RequiresAuthentication
	public ResponseEntity handle(@Valid @RequestBody TagScrapRequest tagScrapRequest) throws Exception {
		tagScrapService.handle(tagScrapRequest);
		return new ResponseEntity<>(HttpStatus.OK);
	}

	@ApiOperation(value = "获取报废记录", notes = "获取报废记录")
	@GetMapping
	@ButtonResource(url = "view")
	@RequiresPermissions("scrap.view")
	@RequiresAuthentication
	public Page<TagScrap> getTagScrapList(HttpServletRequest request, final Long printFactoryId,
			final String productId) {
		PageRequest pageable = PageUtil.getPageRequest(request);
		Specification<TagScrap> spec = new Specification<TagScrap>() {
			@Override
			public Predicate toPredicate(Root<TagScrap> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<Predicate>();
				if (context.CURRECT_USER.getEseId() != null
						& context.CURRECT_USER.getEseId().intValue() != CommonConstants.SYSTEM_INNER_ESEID) {
					predicates.add(cb.equal(root.get("eseId").as(Long.class), context.CURRECT_USER.getEseId()));
				}
				if (printFactoryId != null) {
					predicates.add(cb.equal(root.get("printFactoryId").as(Long.class), printFactoryId));
				}
				if (productId != null) {
					predicates.add(cb.equal(root.get("productId").as(Long.class), productId));
				}
				Predicate[] parr = new Predicate[predicates.size()];
				return cb.and(predicates.toArray(parr));
			}
		};
		return tagScrapService.getTagScrapList(spec, pageable);
	}

	@ApiOperation(value = "根据批次id或者名称查询相关批次", notes = "根据批次id或者名称查询相关批次")
	@ResponseBody
	@GetMapping("tagBatchInfo")
	public ResponseEntity<List<TagBatchVO>> tagBatchInfo(String tagBatchIdOrName) {
		if (StringUtils.isNotBlank(tagBatchIdOrName)) {
			Specification<TagBatch> spec = new Specification<TagBatch>() {
				@Override
				public Predicate toPredicate(Root<TagBatch> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
					List<Predicate> predicate = new ArrayList<Predicate>();
					if (context.CURRECT_USER.getEseId() != null
							& context.CURRECT_USER.getEseId().intValue() != CommonConstants.SYSTEM_INNER_ESEID) {
						predicate.add(cb.equal(root.get("eseId").as(Long.class), context.CURRECT_USER.getEseId()));
					}
					if (StringUtils.isNumeric(tagBatchIdOrName)) {
						Predicate p1 = cb.equal(root.get("id").as(Long.class), Long.valueOf(tagBatchIdOrName));
						Predicate p2 = cb.like(root.get("name").as(String.class), "%" + tagBatchIdOrName + "%");
						predicate.add(cb.or(p1, p2));// tagbatchid
					} else {
						predicate.add(cb.like(root.get("name").as(String.class), "%" + tagBatchIdOrName + "%"));// tagbatchname
					}
					Predicate[] parr = new Predicate[predicate.size()];
					return cb.and(predicate.toArray(parr));
				}
			};
			return new ResponseEntity<List<TagBatchVO>>(tagBatchService.findTagBatchesBytagBatchIdOrName(spec),
					HttpStatus.OK);
		} else {
			return new ResponseEntity<List<TagBatchVO>>(new ArrayList<TagBatchVO>(), HttpStatus.OK);
		}
	}

	@ApiOperation(value = "根据码序号或者加密串查询", notes = "根据码序号或者加密串查询")
	@ResponseBody
	@GetMapping("singleCodeInfo")
	public ResponseEntity<SingleCodeInfoVO> singleCodeInfo(String codeUrlOrEncryptionStr) throws Exception {
		if (StringUtils.isNoneBlank(codeUrlOrEncryptionStr)) {
			return new ResponseEntity<>(tagScrapService.findSingleCodeInfo(codeUrlOrEncryptionStr), HttpStatus.OK);
		} else {
			return new ResponseEntity<>(new SingleCodeInfoVO(), HttpStatus.OK);
		}
	}

	@ApiOperation(value = "根据箱码序号或者url查询", notes = "根据箱码序号或者url查询")
	@ResponseBody
	@GetMapping("packageCodeInfo")
	public ResponseEntity<PackageCodeInfoVO> packageCodeInfo(String packageUrlOrSerialNumber) throws Exception {
		if (StringUtils.isNoneBlank(packageUrlOrSerialNumber)) {
			return new ResponseEntity<>(tagScrapService.findPackageCodeInfo(packageUrlOrSerialNumber),HttpStatus.OK);
		} else {
			return new ResponseEntity<>(new PackageCodeInfoVO(), HttpStatus.OK);
		}
	}

}
